// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include <vector>

#include <gtest/gtest.h>

#include "DataStructure/Common/Validation.h"

#include "DBManager/IService/Input/Parameter/IParameterService.h"
#include "DBManager/UnitTest/HDF5/TestDB.h"

using namespace SG::DBManager;
using namespace SG::Utility;

TEST (I_ParameterTest, ParameterData)
{
    if (DB::ServiceFactory != nullptr)
    {
        DB::ServiceFactory->ClearDatabase ();
    }

    auto service = DB::ServiceFactory->get<IParameterService> ();
    try
    {
        SGParameter p;
        p.AddString ("str", "hello");
        p.AddBool ("bool", false);

        p.AddDouble ("d", 66.6);

        SGParameter sec;
        {
            sec.AddInt ("i", 666);

            sec.AddEmptyArray ("arr");
            sec.GetValue ("arr").Append (1);
            sec.GetValue ("arr").Append (2);
            sec.GetValue ("arr").Append (99.9);

            sec.GetValue ("i").SetInt (888);
        }

        p.AddValue ("sec", sec);
        service->Initial (p);
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what () << '\n';
    }

    SGParameter P1 = service->GetSolverParameter ();

    ASSERT_EQ (
        R"({
    "BOOL": false,
    "D": 66.6,
    "SEC": {
        "ARR": [
            1,
            2,
            99.9
        ],
        "I": 888
    },
    "STR": "hello"
})",
        P1.PrettyPrintJsonString ());

    service = DB::ServiceFactory->get<IParameterService> ();

    // 保存数据
    service->SetCustomParameter ("str", std::string ("world"));
    service->SetCustomParameter ("bool", true);
    service->SetCustomParameter ("d", 99.9);
    service->SetCustomParameter ("i", 999);

    // 提取数据
    SGParameter customParam = service->GetCustomParameter ();

    ASSERT_EQ (customParam["str"].GetString (), "world");
    ASSERT_EQ (customParam.GetValue ("bool").LookupOrDefault (false), true);

    double d = customParam.GetValue ("d").LookupOrDefault (0.0);
    ASSERT_EQ (SG::DataStructure::Common::isNear (d, 99.9), true);

    ASSERT_EQ (customParam.GetValue ("i").LookupOrDefault (0), 999);
}

#include "DBManager/IService/Input/Parameter/INLPARMService.h"

using namespace SG::DBManager;
using namespace SG::DataStructure::FEM;

TEST (I_ParameterTest, NLPARMTest)
{
    static const SG::DataStructure::Common::Id sId = 99;

    if (DB::ServiceFactory != nullptr)
    {
        DB::ServiceFactory->ClearDatabase ();

        // 对MPC数据的处理
        // 先添加MPC
        SG::DataStructure::FEM::NLPARMData nlparmData;
        nlparmData.m_id = sId;
        // mpc.m_Y         = 1;
        DB::ServiceFactory->get<INLPARMService> ()->Add (nlparmData);
    }

    // GetMPCs
    SG::DataStructure::FEM::NLPARMData _OUT nlparmData;
    DB::ServiceFactory->get<INLPARMService> ()->FindById (sId, nlparmData);

    ASSERT_EQ (nlparmData.m_id, 99);
}

#include "DBManager/IService/Input/Parameter/IDAMPINGService.h"
TEST (I_ParameterTest, DAMPINGDatatest)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取服务
    auto service = DB::ServiceFactory->get<IDAMPINGService> ();

    SG::DataStructure::Common::Id const id = 55;

    // 创建对象
    DAMPINGData obj;
    obj.m_sId = 1;
    ASSERT_EQ (service->Add (obj), SG::DataStructure::Common::Status::STATUS_Success);

    // 创建对象
    obj.m_sId = id;

    // 添加对象
    ASSERT_EQ (service->Add (obj), SG::DataStructure::Common::Status::STATUS_Success);

    std::vector<DAMPINGData> _OUT outData;
    ASSERT_EQ (service->FindBySId (id, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.size (), 1);
    ASSERT_EQ (service->Size (), 2);
}

#include "DBManager/IService/Input/Parameter/IHYBDAMPService.h"
TEST (I_ParameterTest, HYBDAMPTest)
{
    DB::ServiceFactory->ClearDatabase ();

    auto service = DB::ServiceFactory->get<IHYBDAMPService> ();

    SG::DataStructure::FEM::HYBDAMPData data;
    data.m_id = 1;
    service->Add (data);

    SG::DataStructure::FEM::HYBDAMPData _OUT outData;
    service->FindById (1, outData);
    ASSERT_EQ (outData.m_id, 1);

    ASSERT_EQ (service->FindByIndex (0, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_id, 1);

    ASSERT_EQ (service->Size (), 1);
    ASSERT_EQ (service->Count (1), 1);
}

#include "DBManager/IService/Input/Parameter/ITSTEPService.h"
TEST (I_ParameterTest, TSTEPDatatest)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取服务
    auto service = DB::ServiceFactory->get<ITSTEPService> ();

    SG::DataStructure::Common::Id const id = 55;

    // 创建对象
    TSTEPData obj;
    obj.m_sId = 1;
    ASSERT_EQ (service->Add (obj), SG::DataStructure::Common::Status::STATUS_Success);

    // 创建对象
    obj.m_sId = id;

    // 添加对象
    ASSERT_EQ (service->Add (obj), SG::DataStructure::Common::Status::STATUS_Success);

    TSTEPData _OUT outData;
    ASSERT_EQ (service->FindBySId (id, outData), SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (outData.m_sId, id);
    ASSERT_EQ (service->Size (), 2);
}
